package net.lb.socketserver.transfer.handler.socket;

import java.nio.channels.CompletionHandler;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import net.lb.baseutil.collection.ByteBufferPool;
import net.lb.socketserver.bus.Message;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

@Resource
public class MessageWriteHandler implements CompletionHandler<Integer, Message>
{
    private final Logger logger = LogManager.getLogger();
    
    @Override
    public void completed(Integer result, Message message)
    {
        if (message.getWriteBuffer().hasRemaining())
        {
            if (logger.isTraceEnabled())
            {
                logger.trace("向通道{}数据写入不完整,写入{},当前状态{}", message.getChannelInfo().getAddress(), result, message.getWriteBuffer());
            }
            message.getChannelInfo().getSocketChannel().write(message.getWriteBuffer(), 10, TimeUnit.SECONDS, message, this);
            return;
        }
        else
        {
            ByteBufferPool.returnBuffer(message.getWriteBuffer());
            if (logger.isTraceEnabled())
            {
                logger.trace("向通道{}写入完毕,写入{}", message.getChannelInfo().getAddress(),result);
            }
            Queue<Message> sendQueue = message.getChannelInfo().getSendQueue();
            // 写完毕了，再将message移出队列，此时第二个才可以写。否则就会因为第一个还在写的过程中，第二个就可以判定生效进行再次写监听造成异常
            sendQueue.poll();
            Message next = sendQueue.peek();
            if (next != null)
            {
                next.tryWrite();
            }
        }
    }
    
    @Override
    public void failed(Throwable exc, Message message)
    {
        logger.error("向socket通道{}写入信息失败，关闭通道,buffer状态是{}", message.getChannelInfo().getAddress(), message.getWriteBuffer(), exc);
        ByteBufferPool.returnBuffer(message.getWriteBuffer());
        message.getChannelInfo().close();
    }
    
}
